﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Timers;
using Android.App;
using Android.Content;
using Android.Content.PM;
using Android.Views;
using Android.OS;
using Xamarin.ActionbarSherlockBinding.Views;
using Xamarin.ActionbarSherlockBinding.App;
using String = System.String;
using IMenuItem = Xamarin.ActionbarSherlockBinding.Views.IMenuItem;
using JmShared;

namespace jivemessenger
{

    // ConfigurationChanges = Android.Content.PM.ConfigChanges.Orientation | Android.Content.PM.ConfigChanges.Keyboard| Android.Content.PM.ConfigChanges.KeyboardHidden)
    [Activity(Label = "Jive", Icon = "@drawable/icon", MainLauncher = true, LaunchMode = LaunchMode.SingleTask,
        WindowSoftInputMode = SoftInput.AdjustResize, ConfigurationChanges = ConfigChanges.Orientation|ConfigChanges.ScreenSize)]
    public class ActivityGroupChat : SherlockFragmentActivity
    {
        private const int ContactButtonID = 0;
        private const int ConfigButtonID = 1;
        private const int ConnectButtonID = 2;

        private IMenuItem _contactItem;
        private IMenuItem _configItem;
        private IMenuItem _connectItem;
        //private String[] _mLocations;
        private ChatControl _chatControlFragment;
        private readonly object LockObject = new object();
        private static bool _isActive;

        private Timer _receiptTimer;
        //public bool isConfigurationChange = false;

        public ActivityGroupChat()
        {
            StaticService.IsBound = false;
        }


        protected override void OnCreate(Bundle savedInstanceState)
        {
            if (!IsTaskRoot)
            {
                Intent intent = Intent;
                String action = intent.Action;
                if (intent.HasCategory(Intent.CategoryLauncher) && action != null && action.Equals(Intent.ActionMain))
                {
                    Finish();
                    return;
                }
            }

            base.OnCreate(savedInstanceState);




            // Set our view from the "main" layout resource
            SetContentView(Resource.Layout.GroupChat);
            SupportActionBar.SetDisplayShowHomeEnabled(true);
            //var prefs = PreferenceManager.GetDefaultSharedPreferences(this);

            SupportActionBar.NavigationMode = Xamarin.ActionbarSherlockBinding.App.ActionBar.NavigationModeStandard;
            SupportActionBar.SetDisplayShowTitleEnabled(true);
            //this._mLocations = Resources.GetStringArray(Resource.Array.locations);

            //Context context = SupportActionBar.ThemedContext;
            //var list = ArrayAdapter.CreateFromResource(context, Resource.Array.locations, Resource.Layout.sherlock_spinner_item);
            //list.SetDropDownViewResource(Resource.Layout.sherlock_spinner_dropdown_item);
            this._chatControlFragment = (ChatControl)this.SupportFragmentManager.FindFragmentById(Resource.Id.ChatControlFragment);

            //SupportActionBar.SetListNavigationCallbacks(list, this);

            //Tab tab = SupportActionBar.NewTab();
            //tab.SetTag("ConversationTab");
            //tab.SetText("Group Chat");
            //tab.SetTabListener(this);
            //SupportActionBar.AddTab(tab);

            //tab = SupportActionBar.NewTab();
            //tab.SetTag("ContactTab");
            //tab.SetText("Contacts");
            //tab.SetTabListener(this);
            //SupportActionBar.AddTab(tab);
            StaticSettings.GlobalContext = this;
            //if (savedInstanceState != null)
            //{
            //   // string state = savedInstanceState.GetString("ChatBubbles");
            //    ChatBubbleCollection col = StaticMethods.StringToChatBubbleCollection(StaticSettings.SavedChatBubbles);
            //    if (col != null)
            //    {
            //        _chatControlFragment.AddChatBubbles(col.ChatBubbles);

            //    }
            //}

            _receiptTimer = new Timer();
            _receiptTimer.Interval = 3000;
            _receiptTimer.Elapsed += new ElapsedEventHandler(_receiptTimer_Elapsed);
            //_receiptTimer.Start();


        }
        //public bool OnNavigationItemSelected(int itemPosition, long itemId)
        //{
        //    switch (itemPosition)
        //    {
        //        case 0:
        //            break;
        //        case 1:
        //            Intent i = new Intent(this.ApplicationContext, typeof(Contacts));
        //            StartActivity(i);
        //            break;
        //    }
        //    return true;
        //}
        void _receiptTimer_Elapsed(object sender, ElapsedEventArgs e)
        {
            if (!StaticService.IsBound)
            {
                _receiptTimer.Stop();
                return;
            }
            lock (LockObject)
            {
                List<int> toRemove = new List<int>();
                foreach (var v in StaticService.Binder.Service.Connection.SentMessages)
                {
                    if (DateTime.Now.Subtract(v.Value.Key).TotalSeconds > 3)
                    {
                        this.DisplayMessage(v.Value.Value.Sender, String.Format("Message response timeout. It is possible the message was not received: {0}", v.Value.Value.Message), MessageType.Error, DateTime.Now);
                        toRemove.Add(v.Key);
                    }
                }
                foreach (int i in toRemove)
                    StaticService.Binder.Service.Connection.SentMessages.Remove(i);
            }
        }

        protected override void OnResume()
        {
            _isActive = true;
            base.OnResume();
            _receiptTimer.Start();
        }
        protected override void OnPause()
        {
            _isActive = false;
            base.OnPause();
            _receiptTimer.Stop();
        }
        public override bool OnKeyDown(Keycode keyCode, KeyEvent e)
        {
            if (keyCode == Keycode.Menu)
            {
                if (e.Action == KeyEventActions.Down && this.GetType() != typeof(ActivityPreferences))
                {
                    Intent configIntent = new Intent(this.ApplicationContext, typeof(ActivityPreferences));
                    StartActivity(configIntent);
                    return true;
                }
            }
            return base.OnKeyUp(keyCode, e);
        }
        public override bool OnCreateOptionsMenu(Xamarin.ActionbarSherlockBinding.Views.IMenu menu)
        {
            //Used to put dark icons on light action bar
            bool isLight = true;//SampleList.THEME == Resource.Style.Theme_Sherlock_Light;

            this._contactItem = menu.Add(Xamarin.ActionbarSherlockBinding.Views.Menu.None, ContactButtonID, Xamarin.ActionbarSherlockBinding.Views.Menu.None, "Contacts");
            this._contactItem.SetShowAsAction(MenuItem.ShowAsActionAlways);
            this._contactItem.SetIcon(isLight ? Android.Resource.Drawable.IcMenuInfoDetails : Android.Resource.Drawable.IcMenuInfoDetails);

            this._configItem = menu.Add(Xamarin.ActionbarSherlockBinding.Views.Menu.None, ConfigButtonID, Xamarin.ActionbarSherlockBinding.Views.Menu.None, "Config");
            this._configItem.SetShowAsAction(MenuItem.ShowAsActionAlways);
            this._configItem.SetIcon(isLight ? Android.Resource.Drawable.IcMenuPreferences : Android.Resource.Drawable.IcMenuPreferences);
            // menu.Add("Config").SetIcon(isLight ? Android.Resource.Drawable.IcMenuPreferences : Android.Resource.Drawable.IcMenuPreferences).SetShowAsAction(MenuItem.ShowAsActionIfRoom);

            //menu.Add("Connect")
            //    .SetIcon(isLight ? Resource.Drawable.ic_menu_login : Resource.Drawable.ic_menu_login)
            //    .SetShowAsAction(MenuItem.ShowAsActionIfRoom);
            this._connectItem = menu.Add(Xamarin.ActionbarSherlockBinding.Views.Menu.None, ConnectButtonID, Xamarin.ActionbarSherlockBinding.Views.Menu.None, "Connect");
            this._connectItem.SetShowAsAction(MenuItem.ShowAsActionAlways);
            this._connectItem.SetIcon(isLight ? Resource.Drawable.ic_menu_login : Resource.Drawable.ic_menu_login);
            return true;
        }
        public override void OnConfigurationChanged(
          Android.Content.Res.Configuration newConfig)
        {
            base.OnConfigurationChanged(newConfig);
            string foo = "";

        }
        public override bool OnOptionsItemSelected(Xamarin.ActionbarSherlockBinding.Views.IMenuItem item)
        {
            switch (item.ItemId)
            {
                case ContactButtonID:
                    Intent contactIntent = new Intent(this.ApplicationContext, typeof(Contacts));
                    StartActivity(contactIntent);
                    // Toast.MakeText(this, "clicked on config", ToastLength.Short).Show();
                    return true;
                case ConfigButtonID:
                    Intent configIntent = new Intent(this.ApplicationContext, typeof(ActivityPreferences));
                    StartActivity(configIntent);
                    // Toast.MakeText(this, "clicked on config", ToastLength.Short).Show();
                    return true;
                case ConnectButtonID:
                    this.StartNetworkService();

                    //Toast.MakeText(this, "clicked on connect", ToastLength.Short).Show();
                    return true;
            }
            return base.OnOptionsItemSelected(item);
        }

        //public void OnTabSelected(Tab tab, Android.Support.V4.App.FragmentTransaction ft)
        //{
        //    string tag = tab.Tag.ToString();

        //    Fragment f = SupportFragmentManager.FindFragmentByTag(tag);
        //    if (f != null)
        //    {
        //        ft.Show(f);
        //        return;
        //    }

        //    //  if (tag == "ConversationTab")
        //    Fragment chatControlFrag = new ChatControl();

        //    ft.Add(Resource.Id.linearLayoutWrapper, chatControlFrag, "ConversationTab");
        //    Fragment contactFrag = new Contacts();


        //    ft.Add(Resource.Id.linearLayoutWrapper, contactFrag, "ContactTab");

        //    // else if (tag == "ContactTab")
        //    ft.Show(chatControlFrag);




        //}

        void chatControl_SendMessageEvent(object sender, NewChatMessageEventArgs e)
        {
            if (StaticService.Binder == null)
                return;
            if (!StaticService.Binder.Service.Connection.SendMessage(e.Message))
            {
                DisplayMessage(Client.CurrentUserInfo, String.Format("Could not deliver message: \r\n{0}", e.Message.Message), MessageType.Error, DateTime.Now);
            }
            else
                StaticService.Binder.Service.Connection.SentMessages.Add(e.Message.MessageID.Value, new KeyValuePair<DateTime, ChatMessage>(DateTime.Now, e.Message));
        }
        protected override void OnDestroy()
        {
            base.OnDestroy();
            if (IsFinishing)
                this.StopNetworkService(true);
        }

        private void StopNetworkService(bool unbindService)
        {
          
            if (StaticService.IsBound)
            {
                if (unbindService)
                {
                    StaticService.Binder.Service.RunBeforeUnbind();
                    UnbindService(StaticService.ServiceConnection);
                    StopService(new Intent(this, typeof (JiveService)));
                    StaticService.IsBound = false;
                    StaticService.ServiceConnection.ServiceConnectionChangedEvent -= new EventHandler<JiveServiceConnectEventArgs>(ServiceConnection_ServiceConnectedEvent);
                    StaticService.Binder.Service.NewMessageEvent -= new EventHandler<NewChatMessageEventArgs>(ActivityGroupChat_NewMessageEvent);
                    StaticService.Binder.Service.OnDisconnectEvent -= new EventHandler<JiveServiceConnectEventArgs>(Service_OnDisconnectEvent);

                }
                ConnectUpdateUI(false);
                //DisplayMessage(String.Format("{0} has left the conversation", Client.CurrentUserInfo.PrettyName), Client.CurrentUserInfo, MessageType.Message, DateTime.Now);
            }
        }
        /// <summary>
        /// Binds to the network service if it is unbound, or unbinds the network service if it is bound.
        /// </summary>
        private void StartNetworkService()
        {
            if (StaticService.IsBound)
            {
                //  ServiceConnection.ServiceConnectedEvent -= new EventHandler<JiveServiceConnectEventArgs>(ServiceConnection_ServiceConnectedEvent);
                if (Client.IsLoggedIn)
                    this.StopNetworkService(true);
                else
                    StaticService.Binder.Service.ManualConnect();
            }
            else
            {

                var serviceIntent = new Intent(this, typeof (JiveService));//"com.jivemessenger.JiveService");
               // StartService(serviceIntent);

                StaticService.ServiceConnection = new JiveServiceConnection();

                StaticService.ServiceConnection.ServiceConnectionChangedEvent += new EventHandler<JiveServiceConnectEventArgs>(ServiceConnection_ServiceConnectedEvent);

                BindService(serviceIntent, StaticService.ServiceConnection, Bind.AutoCreate);

                
            }
        }
                        
        void Service_OnDisconnectEvent(object sender, JiveServiceConnectEventArgs e)
        {

            this.StopNetworkService(e.UnbindService);

        }

        void ServiceConnection_ServiceConnectedEvent(object sender, JiveServiceConnectEventArgs e)
        {
            if (!e.IsDisconnect)
            {

                StaticService.Binder.Service.NewMessageEvent += new EventHandler<NewChatMessageEventArgs>(ActivityGroupChat_NewMessageEvent);
                StaticService.Binder.Service.OnDisconnectEvent += new EventHandler<JiveServiceConnectEventArgs>(Service_OnDisconnectEvent);
                StaticService.Binder.Service.ManualConnect();
                _receiptTimer.Start();
            }
        }

        void ActivityGroupChat_NewMessageEvent(object sender, NewChatMessageEventArgs e)
        {
            ProcessChatMessage(e.Message);
        }

        //public void OnTabUnselected(Tab tab, Android.Support.V4.App.FragmentTransaction ft)
        //{
        //    string tag = tab.Tag.ToString();

        //    Fragment f = SupportFragmentManager.FindFragmentByTag(tag);
        //    if (f != null)
        //    {
        //        ft.Hide(f);
        //        return;
        //    }
        //}
        private void ConnectUpdateUI(bool isConnected)
        {
            RunOnUiThread(() =>
                {
                    ChatControl chatControl = this._chatControlFragment;//(ChatControl)this.SupportFragmentManager.FindFragmentByTag("ConversationTab");
                    if (isConnected)
                    {
                        this._connectItem.SetIcon(Android.Resource.Drawable.IcMenuCloseClearCancel);

                        chatControl.SendMessageEvent += new EventHandler<NewChatMessageEventArgs>(chatControl_SendMessageEvent);
                    }
                    else
                    {
                        //ContactStackpanel.Children.Clear();
                        this._connectItem.SetIcon(Resource.Drawable.ic_menu_login);
                        //Contacts contactsAc = (Contacts)this.SupportFragmentManager.FindFragmentByTag("ContactTab");
                        //if (Contacts.IsActive)
                        Contacts.ClearContacts();
                        if (Client.CurrentUserInfo != null)
                            DisplayMessage(Client.CurrentUserInfo, Client.CurrentUserInfo.PrettyName + " has left the conversation!", MessageType.Logout, DateTime.Now);
                        else
                            DisplayMessage(Client.RedText, "Could not connect", MessageType.Error, DateTime.Now);

                        chatControl.SendMessageEvent -= new EventHandler<NewChatMessageEventArgs>(chatControl_SendMessageEvent);
                    }

                });
        }

        private void AddUsers(IEnumerable<UserInfo> users)
        {
            if (Contacts.IsActive)
                Contacts.AddContacts(users);
            else
            {
                lock (LockObject)
                {
                    foreach (UserInfo user in users)
                    {
                        if (!Client.ConnectedClients.ContainsKey(user.UserID))
                            Client.ConnectedClients.Add(user.UserID, user);
                    }
                }
            }

        }
        protected override void OnRestoreInstanceState(Bundle savedInstanceState)
        {
            base.OnRestoreInstanceState(savedInstanceState);
            if (savedInstanceState != null)
            {
                string state = savedInstanceState.GetString("ChatBubbles");
                ChatBubbleCollection col = StaticMethods.StringToChatBubbleCollection(state);
                if (col != null)
                {
                    // _chatControlFragment.AddChatBubbles(col.ChatBubbles);
                }
            }
        }
        protected override void OnSaveInstanceState(Bundle outState)
        {
            base.OnSaveInstanceState(outState);
            List<ChatBubble> bubbles = _chatControlFragment.GetChatBubbles();
            ChatBubbleCollection col = new ChatBubbleCollection((bubbles.Count > 50 ? bubbles.Skip(bubbles.Count - 50).ToList() : bubbles));
            StaticSettings.SavedChatBubbles = StaticMethods.ObjectToString<ChatBubbleCollection>(col);
            outState.PutString("ChatBubbles", StaticMethods.ObjectToString<ChatBubbleCollection>(col));
        }
        private void UpdateStatus(UserInfo user)
        {
            if (Contacts.IsActive)
                Contacts.UpdateContact(user);
            lock (LockObject)
            {
                //UserInfo oldUsr = Contacts.UsersToUpdate.Keys.ToList().Find(x => x.UserID == user.UserID);
                //if (oldUsr != null)
                //    Contacts.UsersToUpdate.Remove(oldUsr);
                Client.ConnectedClients[user.UserID] = user;
                //Contacts.UsersToUpdate.Add(user, DateTime.UtcNow);
            }
        }
        private void RemoveUser(UserInfo user)
        {
            if (Contacts.IsActive)
            {
                Contacts.RemoveContact(user);
                this.DisplayMessage(user, user.PrettyName + " has left the conversation!", MessageType.Logout, DateTime.Now);
            }
            else
            {
                lock (LockObject)
                {
                    //UserInfo oldUsr = Contacts.UsersToAdd.Keys.ToList().Find(x => x.UserID == user.UserID);
                    //if (oldUsr != null)
                    //    Contacts.UsersToAdd.Remove(user);

                    //oldUsr = Contacts.UsersToUpdate.Keys.ToList().Find(x => x.UserID == user.UserID);
                    //if (oldUsr != null)
                    //    Contacts.UsersToUpdate.Remove(user);
                    if (Client.ConnectedClients.ContainsKey(user.UserID))
                        Client.ConnectedClients.Remove(user.UserID);
                }
            }


            this.DisplayMessage(user, user.PrettyName + " has left the conversation!", MessageType.Logout, DateTime.Now);
        }
        private void RemoveUser(IEnumerable<UserInfo> users)
        {
            //  Contacts contactsFragment = (Contacts)this.SupportFragmentManager.FindFragmentByTag("ContactTab");//.FindFragmentById(Resource.Layout.Contacts);
            foreach (UserInfo user in users)
            {
                RemoveUser(user);
                //if (Contacts.IsActive)
                //{
                //    Contacts.RemoveContact(user);
                //    this.DisplayMessage(user, user.PrettyName + " has left the conversation!", MessageType.Logout, DateTime.Now);
                //}
                //else
                //{
                //    lock (LockObject)
                //    {
                //        //UserInfo oldUsr = Contacts.UsersToAdd.Keys.ToList().Find(x => x.UserID == v.UserID);
                //        //if (oldUsr != null)
                //        //    Contacts.UsersToAdd.Remove(v);

                //        //oldUsr = Contacts.UsersToUpdate.Keys.ToList().Find(x => x.UserID == v.UserID);
                //        //if (oldUsr != null)
                //        //    Contacts.UsersToUpdate.Remove(v);

                //        if (Client.ConnectedClients.ContainsKey(user.UserID))
                //            Client.ConnectedClients.Remove(user.UserID);

                //    }
                //}
            }
        }
        private void ProcessChatMessage(ChatMessage msg)
        {
            //try
            //{
            switch (msg.MessageType)
            {
                case MessageType.LoginFailed:
                    {

                        MessageBox.Show("Wrong username or password.");
                        ConnectUpdateUI(false);
                        break;
                    }
                case MessageType.LoginSuccessful:
                    {
                        if (Client.IsLoggedIn)
                            return;
                        Client.CurrentUserInfo = msg.Sender;

                        Client.IsLoggedIn = true;
                        ConnectUpdateUI(true);
                        this.DisplayMessage(Client.CurrentUserInfo, "Login successful", msg.MessageType, msg.TimeStampMessageRelayed);
                        //App.RegisterPush(true, App.AppSettings.IsToastNotificationEnabledSetting);
                        DeviceInfo dev = new DeviceInfo();

                        dev.IsActive = true;
                        dev.IsTileEnabled = StaticSettings.IsTileNotificationEnabledSetting;
                        dev.IsToastEnabled = StaticSettings.IsToastNotificationEnabledSetting;
                        dev.OfflineMessagesAgeLimit = StaticSettings.OfflineMessagesAgeLimit;
                        dev.OfflineMessagesCountLimit = StaticSettings.OfflineMessagesCountLimit;
                        dev.StoreMessagesWhileOffline = StaticSettings.StoreMessagesWhileOffline;

                        string payload = StaticMethods.ObjectToString<DeviceInfo>(dev);
                        StaticService.Binder.Service.Connection.SendStatusMessage(MessageType.ResetUnreadMessageCount, payload);
                        JiveGCM.Register();


                        break;
                    }
                case MessageType.Authenticated:
                    {
                        AddUsers(msg.UserInfo);
                        if (Client.ConnectedClients.Values.ToList().FindAll(x => x.UserName == msg.Sender.UserName).Count == 1)
                            this.DisplayMessage(msg.Sender, msg.Sender.PrettyName + " has been added to the conversation.", msg.MessageType, msg.TimeStampMessageRelayed);
                        break;
                    }
                case MessageType.Message:
                    {
                        this.DisplayMessage(msg.Sender, msg.Message, msg.MessageType, msg.TimeStampMessageRelayed);
                        break;
                    }
                case MessageType.PM:
                    {
                        //ReveivePM(msg);
                        break;
                    }
                case MessageType.Hello:
                    {
                        AddUsers(msg.UserInfo);
                        foreach (UserInfo u in msg.UserInfo)
                        {
                            UpdateStatus(u);
                        }
                        break;
                    }
                case MessageType.UpdateUserInfo:
                    {
                        AddUsers(msg.UserInfo);
                        break;
                    }
                case MessageType.Logout:
                    {
                        RemoveUser(msg.UserInfo);
                        break;
                    }

                case MessageType.Busy:
                case MessageType.AFK:
                    {

                        UpdateStatus(msg.Sender);

                        break;
                    }

                //case MessageType.BroadcastEmoticons:
                //    {

                //        ProcessCustomContactEmoticons(msg);
                //        break;
                //    }
                //case MessageType.RequestingEmoticon:
                //    {
                //        if (!StaticSettings.IsWifiEnabled)
                //            return;//don't transfer emoticon images without wifi

                //        if (!StaticSettings.CustomEmoticons.ContainsKey(msg.Message))
                //            break;
                //        if (String.IsNullOrEmpty(StaticSettings.CustomEmoticons[msg.Message]))
                //            break;
                //        ContactEmoticon ce = new ContactEmoticon
                //        {
                //            KeyWord = msg.Message,
                //            Emoticon = Convert.ToBase64String(StaticMethods.ImageToByteArray(StaticSettings.GetEmoticons(Client.CurrentUserInfo, true, true)[msg.Message]))
                //        };
                //        msg.Message = StaticMethods.ContactEmoticonToString(ce);
                //        msg.MessageType = MessageType.SendingEmoticon;
                //        UserInfo receiver = msg.Sender;
                //        msg.UserInfo = new UserInfo[1];
                //        msg.UserInfo[0] = receiver;
                //        msg.Sender = Client.CurrentUserInfo;
                //        Connection.SendMessage(msg);
                //        break;
                //    }
                //case MessageType.SendingEmoticon:
                //    {

                //        ReceiveEmoticon(msg);

                //        break;
                //    }
            }
        }
        //public void OnTabReselected(Tab tab, Android.Support.V4.App.FragmentTransaction ft)
        //{
        //    //Do nothing
        //}

        private void DisplayMessage(UserInfo sender, object msg, MessageType mt, DateTime timestamp)
        {
            //    GroupChatControl.AppendLineToChatHistory(sender, msg.ToString(), mt, timestamp);
            // ChatControl fragment = (ChatControl)this.SupportFragmentManager.FindFragmentByTag("ConversationTab");//FindFragmentById(Resource.Layout.ChatControl);
            this._chatControlFragment.DisplayChatBubble(sender, msg.ToString(), timestamp);
        }

    }

}

